JPA (Java Persistence API) একটি শক্তিশালী API যা Java অ্যাপ্লিকেশনগুলির জন্য অবজেক্ট-অরিয়েন্টেড ডেটাবেস ইন্টারঅ্যাকশন সরবরাহ করে। সাধারণত, JPA তে JPQL (Java Persistence Query Language) ব্যবহার করে ডেটা অ্যাক্সেস করা হয়, তবে কিছু পরিস্থিতিতে, বিশেষ করে যখন ডেটাবেস নির্দিষ্ট কুয়েরি বা অপ্টিমাইজড কুয়েরি প্রয়োজন হয়, তখন Native SQL Queries ব্যবহার করা হয়ে থাকে।
Native SQL Queries হল সেই SQL কুয়েরি যা ডেটাবেস নির্দিষ্ট এবং JPA এর স্বাভাবিক JPQL কুয়েরির বাইরে থাকে। এটি ডেটাবেসের আসল SQL ভাষায় লেখা হয় এবং EntityManager এর মাধ্যমে চালানো হয়।
Native SQL Queries এর সুবিধা এবং ব্যবহার
- ডেটাবেস নির্দিষ্ট কুয়েরি: কিছু বিশেষ SQL ফিচার যেমন JOINs, GROUP BY, HAVING, Window Functions ইত্যাদি JPQL তে সম্ভব নয়, তখন Native SQL কুয়েরি ব্যবহৃত হয়।
- পারফরম্যান্স অপটিমাইজেশন: Native SQL কুয়েরি ডেটাবেসের পারফরম্যান্স সঠিকভাবে টিউন করতে সাহায্য করতে পারে, কারণ এটি ডেটাবেসের বিশেষ ক্ষমতা বা ফিচার ব্যবহার করতে সক্ষম।
- বিকল্প কুয়েরি লেখার ক্ষমতা: কিছু কেসে JPQL নির্দিষ্ট ফিচার বা ফাংশন সাপোর্ট করে না, তখন Native SQL Query লেখার মাধ্যমে আপনি ডেটাবেসের পূর্ণ ক্ষমতা ব্যবহার করতে পারেন।
Native SQL Query ব্যবহার করার পদ্ধতি
EntityManager ব্যবহার করে Native SQL Query চালানো হয়। Native SQL Query চালানোর জন্য createNativeQuery() মেথড ব্যবহার করা হয়।
1. Native SQL Query ব্যবহার করা
উদাহরণ: Native SQL Query with Entity Mapping
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Employee> findEmployeesWithSalaryGreaterThan(double salary) {
// Native SQL Query to fetch employees with salary greater than a specified value
String sql = "SELECT * FROM Employee WHERE salary > :salary";
Query query = entityManager.createNativeQuery(sql, Employee.class);
query.setParameter("salary", salary);
return query.getResultList();
}
}
এখানে, একটি Native SQL Query ব্যবহার করা হয়েছে যা Employee টেবিল থেকে সকল কর্মচারী নির্বাচন করবে, যাদের salary একটি নির্দিষ্ট মানের বেশি।
- createNativeQuery: Native SQL Query তৈরি করতে ব্যবহৃত হয়।
- Employee.class: এখানে আমরা এই SQL Query এর জন্য Employee Entity ক্লাসের মডেল ব্যবহার করেছি।
- setParameter(): salary প্যারামিটারটি সেট করা হয়েছে।
উদাহরণ: Native SQL Query without Entity Mapping
যদি আপনি Native SQL Query ব্যবহার করে কিছু নির্দিষ্ট ডেটা ফেরত পেতে চান, কিন্তু Entity ক্লাসে সেই ডেটা ম্যাপ করতে চান না, তাহলে createNativeQuery() এর মাধ্যমে আপনি সোজাসুজি Object Array বা Object[] রিটার্ন করতে পারেন।
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Object[]> findEmployeeNamesAndSalaries() {
// Native SQL Query to fetch employee names and salaries
String sql = "SELECT name, salary FROM Employee";
Query query = entityManager.createNativeQuery(sql);
return query.getResultList();
}
}
এখানে, Object[] রিটার্ন হচ্ছে যেখানে প্রতিটি Array এর মধ্যে name এবং salary ফিল্ড থাকবে। এই ক্ষেত্রে Entity ক্লাসের Mapping প্রয়োজন নেই।
2. Native SQL Query with Aggregation Functions
Native SQL Query তে আপনি Aggregation Functions যেমন COUNT, SUM, AVG, MAX, MIN ইত্যাদি ব্যবহার করতে পারেন। যেমন:
public long getEmployeeCountByDepartment(String department) {
String sql = "SELECT COUNT(*) FROM Employee WHERE department = :department";
Query query = entityManager.createNativeQuery(sql);
query.setParameter("department", department);
return ((Number) query.getSingleResult()).longValue();
}
এখানে, আমরা COUNT ফাংশন ব্যবহার করে একটি নির্দিষ্ট department এর Employee সংখ্যা গণনা করছি।
3. Named Native SQL Queries
JPA তে Named Native Queries আপনি @Query অ্যানোটেশন ব্যবহার করে Entity ক্লাসের মধ্যে ডিফাইন করতে পারেন, যাতে কোডে আরো পরিষ্কার এবং রক্ষণাবেক্ষণযোগ্য থাকে।
Named Native Query Example:
@Entity
@NamedNativeQuery(name = "Employee.findByDepartment",
query = "SELECT * FROM Employee WHERE department = :department",
resultClass = Employee.class)
public class Employee {
// Entity class definition
}
এখন, আপনি NamedNativeQuery ব্যবহার করে নিচের মতো ডেটা পেতে পারেন:
Query query = entityManager.createNamedQuery("Employee.findByDepartment");
query.setParameter("department", "HR");
List<Employee> employees = query.getResultList();
4. Pagination in Native Queries
Native SQL Query তে পেজিনেশন (paginated queries) ব্যবহারের জন্য setFirstResult() এবং setMaxResults() ব্যবহার করা যায়।
String sql = "SELECT * FROM Employee WHERE department = :department";
Query query = entityManager.createNativeQuery(sql, Employee.class);
query.setParameter("department", "IT");
query.setFirstResult(0); // Start from the first result
query.setMaxResults(10); // Limit the number of results
List<Employee> employees = query.getResultList();
এখানে, আমরা পেজিনেশন করে IT ডিপার্টমেন্টের প্রথম 10 কর্মচারী নির্বাচিত করেছি।
Native SQL Query এর সুবিধা
- ডেটাবেস নির্দিষ্ট কুয়েরি সমর্থন: যখন আপনাকে ডেটাবেস নির্দিষ্ট কুয়েরি বা অপ্টিমাইজড কুয়েরি চালাতে হয়, তখন Native SQL কুয়েরি অত্যন্ত কার্যকরী।
- পারফরম্যান্স অপটিমাইজেশন: কিছু SQL ফিচার যেমন complex joins বা window functions, যেগুলি JPQL এ সহজে সমাধান করা সম্ভব নয়, Native SQL Query এর মাধ্যমে সরাসরি ডেটাবেসে ব্যবহৃত হয়।
- JPA এর বাইরে SQL ব্যবহার: JPQL এর সীমাবদ্ধতাগুলি এড়িয়ে Native SQL ব্যবহার করে সরাসরি ডেটাবেসের জন্য কাস্টম SQL কুয়েরি লিখতে পারবেন।
Native SQL Query এর সীমাবদ্ধতা
- ডেটাবেস নির্ভরশীলতা: Native SQL Query ডেটাবেস নির্দিষ্ট, অর্থাৎ এটি এক ডেটাবেসে কাজ করতে পারে, কিন্তু অন্য ডেটাবেসে কাজ নাও করতে পারে।
- JPA Features এর অভাব: JPQL ব্যবহার করলে Entity ও তার সম্পর্কের উপর কাজ করা সহজ, কিন্তু Native SQL Query তে এসব সুবিধা পাওয়া যায় না।
- পরবর্তী রক্ষণাবেক্ষণ সমস্যা: Native SQL ব্যবহার করলে ডেটাবেস কোডের রক্ষণাবেক্ষণ কঠিন হতে পারে, বিশেষত যখন আপনি ডেটাবেস পরিবর্তন করবেন।
সারাংশ
Native SQL Queries JPA তে একটি শক্তিশালী উপায় যা আপনাকে ডেটাবেস নির্দিষ্ট কুয়েরি লেখার সুযোগ দেয়। এটি যখন JPQL সীমাবদ্ধ থাকে বা ডেটাবেসের নির্দিষ্ট ফিচার প্রয়োজন হয়, তখন কার্যকরী হয়। Native SQL তে complex SQL কুয়েরি, joins, aggregation ফাংশন, এবং পেজিনেশন ব্যবহার করা যায় যা ডেটাবেসের পারফরম্যান্স অপটিমাইজেশন করতে সাহায্য করে।
JPA (Java Persistence API) তে Native Queries চালানোর প্রক্রিয়া একটি শক্তিশালী উপায় যা আপনাকে ডেটাবেস নির্দিষ্ট SQL কুয়েরি চালানোর সুযোগ দেয়, বিশেষ করে যখন JPQL (Java Persistence Query Language) সীমাবদ্ধ হয়ে যায় অথবা আপনি ডেটাবেসের নিজস্ব ফিচার ব্যবহার করতে চান। Native SQL কুয়েরি EntityManager ব্যবহার করে চালানো হয় এবং এটি ডেটাবেসের আসল SQL সিনট্যাক্স ব্যবহার করে।
Native Queries চালানোর জন্য EntityManager ব্যবহার করা
JPA তে Native SQL Query চালানোর জন্য EntityManager এর createNativeQuery() মেথড ব্যবহার করা হয়। EntityManager কুয়েরি চালানোর জন্য একটি API প্রদান করে যা Native SQL কুয়েরি লেখার এবং ফলাফল পাওয়ার জন্য ব্যবহৃত হয়।
Native Query চালানোর ধাপসমূহ:
- Native SQL Query লেখার জন্য
createNativeQuery()মেথড ব্যবহার করুন। - Query object তৈরি করুন এবং সেই Query তে parameter পাস করুন (যদি প্রয়োজন হয়)।
- Query execute করুন এবং ফলাফল সংগ্রহ করুন।
Native SQL Query চালানোর প্রক্রিয়া:
1. Native SQL Query with Entity Mapping
এই প্রক্রিয়ায়, আমরা Native SQL Query চালানোর জন্য Entity Class ব্যবহার করব, যাতে SQL Query এর ফলাফল সরাসরি Entity তে ম্যাপ করা যায়।
উদাহরণ:
ধরা যাক, আপনার কাছে Employee Entity ক্লাস রয়েছে এবং আপনি salary এর উপর ভিত্তি করে কর্মচারীদের তালিকা দেখতে চান। আপনার Native SQL Query হবে:
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Employee> findEmployeesWithSalaryGreaterThan(double salary) {
// Native SQL Query to fetch employees with salary greater than a specified value
String sql = "SELECT * FROM Employee WHERE salary > :salary";
Query query = entityManager.createNativeQuery(sql, Employee.class);
query.setParameter("salary", salary);
return query.getResultList();
}
}
এখানে:
createNativeQuery()মেথডের মাধ্যমে Native SQL Query তৈরি করা হয়েছে।Employee.classনির্দেশ করছে যে, SQL Query এর ফলাফল Employee Entity তে ম্যাপ হবে।setParameter("salary", salary)প্যারামিটারটি সেট করে কাজ করা হয়েছে।
2. Native SQL Query without Entity Mapping
যখন আপনি Native SQL Query চালাতে চান কিন্তু Entity ক্লাসে সেই ডেটা ম্যাপ করতে চান না, তখন createNativeQuery() মেথডটি সরাসরি Object[] অথবা Object ব্যবহার করে ফলাফল ফেরত দিতে পারে।
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Object[]> findEmployeeNamesAndSalaries() {
// Native SQL Query to fetch employee names and salaries
String sql = "SELECT name, salary FROM Employee";
Query query = entityManager.createNativeQuery(sql);
return query.getResultList();
}
}
এখানে:
Object[]আউটপুট টাইপেnameএবংsalaryকলামসমূহের মান ফেরত আসবে।- ফলস্বরূপ,
query.getResultList()কল করলে এটি একটি List<Object[]> ফেরত দেবে যেখানে প্রতিটি উপাদান একটি Array হবে।
3. Native SQL Query with Aggregation Functions
Native SQL Query তে aggregation functions (যেমন COUNT, SUM, AVG, MAX, MIN) ব্যবহার করা যায়। এখানে, আমরা Employee টেবিল থেকে salary এর উপর ভিত্তি করে গড় (average) গণনা করব।
public double getAverageSalary() {
String sql = "SELECT AVG(salary) FROM Employee";
Query query = entityManager.createNativeQuery(sql);
return (Double) query.getSingleResult();
}
এখানে:
- AVG(salary) দ্বারা কর্মচারীদের salary এর গড় বের করা হচ্ছে।
getSingleResult()মেথড ব্যবহার করে একটি একক মান (গড় salary) ফেরত পেয়েছি।
4. Native SQL Query with Named Parameters
যখন আপনার Native SQL Query তে প্যারামিটার থাকে, তখন named parameters ব্যবহার করা যেতে পারে:
public List<Employee> findEmployeesByDepartment(String department) {
String sql = "SELECT * FROM Employee WHERE department = :department";
Query query = entityManager.createNativeQuery(sql, Employee.class);
query.setParameter("department", department);
return query.getResultList();
}
এখানে:
:departmentপ্যারামিটারটি SQL Query তে named parameter হিসেবে ব্যবহৃত হচ্ছে।setParameter()মেথড ব্যবহার করে আমরা প্যারামিটারটি পাস করেছি।
5. Native SQL Query with Pagination
Native SQL Query তে পেজিনেশন (Paginated Results) ব্যবহার করার জন্য setFirstResult() এবং setMaxResults() ব্যবহার করা হয়।
public List<Employee> getPaginatedEmployees(int pageNumber, int pageSize) {
String sql = "SELECT * FROM Employee";
Query query = entityManager.createNativeQuery(sql, Employee.class);
query.setFirstResult((pageNumber - 1) * pageSize);
query.setMaxResults(pageSize);
return query.getResultList();
}
এখানে:
setFirstResult(): এটি প্রথম ফলাফলটি নির্ধারণ করে।setMaxResults(): এটি প্রতি পৃষ্ঠায় প্রদর্শিত সর্বোচ্চ ফলাফল সংখ্যা নির্ধারণ করে।
Native SQL Queries এর সুবিধা:
- ডেটাবেস নির্দিষ্ট কুয়েরি সাপোর্ট: যখন ডেটাবেস নির্দিষ্ট কুয়েরি বা অপ্টিমাইজড কুয়েরি চালাতে হয়, Native SQL খুবই কার্যকর।
- পারফরম্যান্স অপ্টিমাইজেশন: JPQL এর চেয়ে Native SQL কুয়েরি ডেটাবেসের নিজস্ব ক্ষমতা ব্যবহার করতে সাহায্য করতে পারে, যেমন indexing, optimizing joins, ইত্যাদি।
- ফিচার অ্যাক্সেস: কিছু ফিচার যেমন Window Functions, Full Text Search ইত্যাদি JPQL তে নেই, কিন্তু Native SQL তে ব্যবহার করা সম্ভব।
Native SQL Queries এর সীমাবদ্ধতা:
- ডেটাবেস নির্ভরশীলতা: Native SQL কুয়েরি ডেটাবেস নির্দিষ্ট হয়, অর্থাৎ এটি এক ডেটাবেসে কাজ করতে পারে, কিন্তু অন্য ডেটাবেসে কাজ নাও করতে পারে।
- JPQL সুবিধার অভাব: Native SQL কুয়েরি JPA এর শক্তিশালী Entity Relationships এবং automatic mapping সুবিধাগুলি সরবরাহ করে না।
- ডিবাগিং এবং রক্ষণাবেক্ষণ: Native SQL কুয়েরি কোডের রক্ষণাবেক্ষণ এবং ডিবাগিং সহজ নয়, বিশেষত যখন ডেটাবেসের মধ্যে পরিবর্তন আনা হয়।
সারাংশ
Native SQL Queries JPA তে ডেটাবেস নির্দিষ্ট কুয়েরি চালানোর একটি কার্যকরী উপায়। এটি EntityManager ব্যবহার করে createNativeQuery() মেথডের মাধ্যমে তৈরি করা হয় এবং এটি ডেটাবেসের আসল SQL সিনট্যাক্স ব্যবহার করে। Native SQL Queries JPQL এর তুলনায় অধিক কার্যকরী হতে পারে যখন complex joins, aggregation functions, window functions, বা database-specific features দরকার হয়। তবে, এর কিছু সীমাবদ্ধতা রয়েছে, যেমন এটি ডেটাবেস নির্ভরশীল, এবং জেপিএ এর automatic object mapping সুবিধাগুলি সরবরাহ করে না।
JPA (Java Persistence API)-তে ডেটা অ্যাক্সেস করতে প্রধানত JPQL (Java Persistence Query Language) এবং Native SQL Queries ব্যবহার করা হয়। @Query এবং EntityManager.createNativeQuery() দুটি গুরুত্বপূর্ণ টুল যা ডেটাবেসের সাথে ইন্টারঅ্যাক্ট করতে ব্যবহৃত হয়।
- @Query: এটি Spring Data JPA এ ব্যবহৃত হয়, যেখানে আপনি JPQL বা SQL কুয়েরি লিখে ডেটাবেস অ্যাক্সেস করতে পারেন।
- EntityManager.createNativeQuery(): এটি JPA এর একটি মেথড যা Native SQL Queries চালানোর জন্য ব্যবহৃত হয়, যেখানে সরাসরি ডেটাবেসের আসল SQL ব্যবহার করা হয়।
এখানে আমরা @Query এবং EntityManager.createNativeQuery() এর ব্যবহার এবং পার্থক্য নিয়ে বিস্তারিত আলোচনা করব।
@Query এর ব্যবহার
@Query অ্যানোটেশন Spring Data JPA তে ব্যবহৃত হয় এবং এটি ডেটাবেসে JPQL বা Native SQL কুয়েরি চালানোর জন্য ব্যবহার করা হয়। যখন আপনি Spring Data JPA Repository ব্যবহার করেন, তখন @Query অ্যানোটেশনটি আপনার কাস্টম কুয়েরি সংজ্ঞায়িত করতে সাহায্য করে।
@Query উদাহরণ (JPQL)
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
// JPQL query example using @Query annotation
@Query("SELECT e FROM Employee e WHERE e.department = :department")
List<Employee> findEmployeesByDepartment(String department);
}
এখানে:
- @Query ব্যবহার করা হয়েছে
EmployeeEntity এর department ফিল্ডে ভিত্তি করে কর্মচারীদের তালিকা ফেরত দেওয়ার জন্য। - এটি JPQL কুয়েরি, যেখানে Employee একটি Entity ক্লাস এবং department একটি ফিল্ড।
@Query উদাহরণ (Native SQL)
@Query অ্যানোটেশনটি Native SQL কুয়েরি ব্যবহারের জন্যও ব্যবহৃত হতে পারে, যেমন:
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import java.util.List;
public interface EmployeeRepository extends CrudRepository<Employee, Long> {
// Native SQL query example using @Query annotation
@Query(value = "SELECT * FROM Employee WHERE department = :department", nativeQuery = true)
List<Employee> findEmployeesByDepartmentNative(String department);
}
এখানে:
- nativeQuery = true ব্যবহৃত হয়েছে যাতে Spring Data JPA জানে যে এটি একটি Native SQL কুয়েরি।
- SELECT * FROM Employee এক্সাক্ট SQL কুয়েরি যা Employee টেবিল থেকে ডেটা ফেরত দেবে।
EntityManager.createNativeQuery() এর ব্যবহার
EntityManager.createNativeQuery() JPA এর একটি মেথড যা Native SQL Queries চালানোর জন্য ব্যবহৃত হয়। এই মেথডটি আপনি যখন সরাসরি SQL কুয়েরি লিখতে চান বা ডেটাবেসের নির্দিষ্ট ফিচার ব্যবহার করতে চান তখন ব্যবহার করতে পারেন।
EntityManager.createNativeQuery() উদাহরণ
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Employee> findEmployeesByDepartment(String department) {
// Native SQL query to fetch employees by department
String sql = "SELECT * FROM Employee WHERE department = :dept";
// Create Native Query
Query query = entityManager.createNativeQuery(sql, Employee.class);
query.setParameter("dept", department);
// Execute the query and return results
return query.getResultList();
}
}
এখানে:
- createNativeQuery() ব্যবহার করা হয়েছে Native SQL কুয়েরি তৈরি করতে।
- Employee.class ব্যবহার করা হয়েছে ফলাফল হিসেবে Employee Entity ফিরিয়ে দেওয়ার জন্য।
- setParameter() ব্যবহার করে
:deptপ্যারামিটারটি সেট করা হয়েছে।
EntityManager.createNativeQuery() এর সাথে Object Mapping
কিছু ক্ষেত্রে, আপনি Native SQL কুয়েরি থেকে Object রিটার্ন করতে পারেন। এর জন্য, আপনি resultClass বা Object[] ব্যবহার করতে পারেন।
public List<Object[]> findEmployeeNamesAndSalaries() {
String sql = "SELECT name, salary FROM Employee";
// Create Native Query
Query query = entityManager.createNativeQuery(sql);
// Execute the query and return results
return query.getResultList();
}
এখানে, SQL কুয়েরি name এবং salary ফিল্ডের মান দিচ্ছে, এবং ফলাফলটি Object[] হিসেবে ফেরত দিচ্ছে।
@Query এবং EntityManager.createNativeQuery() এর পার্থক্য
| বৈশিষ্ট্য | @Query (Spring Data JPA) | EntityManager.createNativeQuery() |
|---|---|---|
| ব্যবহার | Spring Data JPA এর Repository তে কাস্টম কুয়েরি লেখার জন্য ব্যবহৃত হয় | JPA এর EntityManager এর মাধ্যমে Native SQL কুয়েরি চালানোর জন্য |
| JPQL বা Native SQL | JPQL বা Native SQL, উভয়ই সমর্থিত | মূলত Native SQL কুয়েরি ব্যবহৃত হয় |
| ডেটা মডেল ম্যাপিং | JPQL কুয়েরি Entity ক্লাসে রূপান্তরিত হয় | Native SQL কুয়েরি Entity বা ResultSet-এ রূপান্তরিত হয় |
| সহজ ইন্টিগ্রেশন | Spring Data JPA Repository এবং @Query খুব সহজে ইন্টিগ্রেট করা যায় | EntityManager এবং Native SQL Query এর সাথে কোড লেখা কিছুটা জটিল |
| ফ্লেক্সিবিলিটি | @Query ডেটাবেস ইন্টারঅ্যাকশন কাস্টমাইজেশন সহজ করে | Native SQL Queries ডেটাবেস নির্দিষ্ট কাস্টমাইজেশন বেশি সক্ষম |
সারাংশ
@Query এবং EntityManager.createNativeQuery() দুইটি গুরুত্বপূর্ণ উপায় যা JPA তে Native SQL Queries চালানোর জন্য ব্যবহৃত হয়।
- @Query অ্যানোটেশন Spring Data JPA ব্যবহারকারীদের জন্য সহজে JPQL বা Native SQL কুয়েরি চালানোর সুযোগ দেয়।
- EntityManager.createNativeQuery() Java EE তে JPA ব্যবহার করে Native SQL কুয়েরি চালানোর জন্য সরাসরি ব্যবহৃত হয়, এবং এতে আপনি Entity বা Object[] রিটার্ন করতে পারেন।
যতটুকু সম্ভব JPQL ব্যবহার করার চেষ্টা করুন, তবে যখন Native SQL বা ডেটাবেস নির্দিষ্ট কুয়েরি প্রয়োজন হয়, তখন createNativeQuery() ব্যবহারের মাধ্যমে ডেটাবেসের শক্তিশালী ফিচার ব্যবহার করতে পারেন।
JPA (Java Persistence API) আপনাকে JPQL (Java Persistence Query Language) ব্যবহার করে Entity গুলির সাথে ইন্টারঅ্যাক্ট করার সুবিধা প্রদান করে। তবে, কিছু জটিল ডেটাবেস অপারেশন বা ডেটাবেস নির্দিষ্ট ফিচার (যেমন complex joins, subqueries, aggregate functions) ব্যবহার করার জন্য Native SQL Queries অত্যন্ত কার্যকরী হতে পারে। Native SQL Queries সরাসরি ডেটাবেসে SQL কুয়েরি পাঠানোর মাধ্যমে complex database operations সম্পাদন করতে সহায়তা করে।
Native Queries দিয়ে Complex Database Operations
JPA তে Native SQL Query ব্যবহার করার মাধ্যমে আপনি ডেটাবেসের কিছু জটিল অপারেশন খুব সহজেই করতে পারেন, যেমন:
- Complex Joins (JOIN Operations)
- Aggregate Functions (COUNT, SUM, AVG, etc.)
- Subqueries
- Group By and Having
- Pagination
এগুলো JPA তে Native SQL Query ব্যবহার করে কীভাবে করা যায়, তা নিচে বিস্তারিতভাবে দেখানো হবে।
1. Complex Joins
Joins সাধারণত বিভিন্ন টেবিলের মধ্যে সম্পর্ক স্থাপন করতে ব্যবহৃত হয়। জটিল INNER JOIN, LEFT JOIN বা RIGHT JOIN ব্যবহারের মাধ্যমে আপনি একাধিক টেবিল থেকে ডেটা সংগ্রহ করতে পারেন।
উদাহরণ: Complex Join using Native Query
ধরা যাক, আমাদের দুটি টেবিল Employee এবং Department রয়েছে এবং আমরা Employee এবং Department টেবিলের মধ্যে INNER JOIN করতে চাই।
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Object[]> findEmployeeDepartmentDetails() {
// Native SQL Query with JOIN operation
String sql = "SELECT e.name, e.salary, d.name FROM Employee e " +
"INNER JOIN Department d ON e.department_id = d.id";
Query query = entityManager.createNativeQuery(sql);
return query.getResultList(); // Execute the query and return the result
}
}
এখানে:
- INNER JOIN ব্যবহার করে
EmployeeএবংDepartmentটেবিলের মধ্যে সম্পর্ক স্থাপন করা হয়েছে। - Object[] রিটার্ন টাইপ ব্যবহার করে একটি এক্সটার্নাল কাস্টম রেজাল্ট ফরম্যাটে ডেটা ফেরত পাওয়া যাবে (এখানে
EmployeeএবংDepartmentএর নাম ও বেতন ফিরে আসবে)।
2. Aggregate Functions (COUNT, SUM, AVG, MAX, MIN)
Aggregate Functions ডেটার উপর সমষ্টিগত অপারেশন সম্পাদন করতে ব্যবহৃত হয়, যেমন রেকর্ডের সংখ্যা, সর্বোচ্চ/সর্বনিম্ন মান, গড় মান, ইত্যাদি।
উদাহরণ: Aggregate Function using Native Query
ধরা যাক, আমরা Employee টেবিলের মধ্যে গড় বেতন বের করতে চাই।
import javax.persistence.EntityManager;
import javax.persistence.Query;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public double getAverageSalary() {
// Native SQL Query to calculate average salary
String sql = "SELECT AVG(salary) FROM Employee";
Query query = entityManager.createNativeQuery(sql);
return (Double) query.getSingleResult(); // Return the average salary
}
}
এখানে:
- AVG(salary) aggregate function ব্যবহার করে
Employeeটেবিলের গড় বেতন বের করা হয়েছে।
3. Subqueries
Subqueries একাধিক কুয়েরির মধ্যে একটি কুয়েরি হতে পারে, যা আরেকটি কুয়েরির ফলাফল ব্যবহার করে। Subqueries জটিল ডেটাবেস অপারেশন করার জন্য ব্যবহার করা হয়, যেখানে একটি কুয়েরির রেজাল্ট অন্য কুয়েরির শর্ত হিসেবে ব্যবহৃত হয়।
উদাহরণ: Using Subquery in Native Query
ধরা যাক, আমরা সেই Employee গুলি খুঁজতে চাই যাদের বেতন গড় বেতনের চেয়ে বেশি।
import javax.persistence.EntityManager;
import javax.persistence.Query;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Employee> findEmployeesWithSalaryGreaterThanAverage() {
// Native SQL Query with Subquery
String sql = "SELECT * FROM Employee e WHERE e.salary > " +
"(SELECT AVG(salary) FROM Employee)";
Query query = entityManager.createNativeQuery(sql, Employee.class);
return query.getResultList(); // Execute the query and return the result
}
}
এখানে:
- Subquery ব্যবহার করা হয়েছে যা গড় বেতন বের করবে এবং তার পরে মূল কুয়েরি সেই বেতনের চেয়ে বেশি বেতন থাকা
Employeeগুলি ফেরত দেবে।
4. Group By and Having
GROUP BY এবং HAVING SQL ফিচার দুটি সাধারণত ডেটাকে গ্রুপ করা এবং একটি শর্তের ভিত্তিতে ডেটা ফিল্টার করার জন্য ব্যবহৃত হয়।
উদাহরণ: Using GROUP BY and HAVING in Native Query
ধরা যাক, আমরা Department অনুযায়ী Employee এর গড় বেতন বের করতে চাই, এবং শুধুমাত্র যেখানে গড় বেতন ৫০,০০০ এর বেশি।
import javax.persistence.EntityManager;
import javax.persistence.Query;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Object[]> getAverageSalaryByDepartment() {
// Native SQL Query with GROUP BY and HAVING
String sql = "SELECT d.name, AVG(e.salary) FROM Employee e " +
"INNER JOIN Department d ON e.department_id = d.id " +
"GROUP BY d.name HAVING AVG(e.salary) > 50000";
Query query = entityManager.createNativeQuery(sql);
return query.getResultList(); // Execute the query and return the result
}
}
এখানে:
- GROUP BY ব্যবহৃত হয়েছে
Departmentঅনুযায়ী গ্রুপিং করার জন্য।
JPA (Java Persistence API) তে Native SQL Queries ব্যবহার করে ডেটা এক্সট্র্যাকশন (Data Extraction) করতে হয়, যখন আপনি JPQL বা Criteria API এর মাধ্যমে যে সমস্ত কুয়েরি বা অপারেশন করতে পারেন না, সেই ক্ষেত্রে Native SQL Queries কার্যকরী হয়ে ওঠে। এটি ডেটাবেস নির্দিষ্ট কুয়েরি বা অপটিমাইজড SQL ফিচারের জন্য ব্যবহৃত হয়।
নিম্নলিখিত উদাহরণগুলোতে আমরা দেখব কীভাবে Native SQL Queries ব্যবহার করে ডেটা এক্সট্র্যাকশন করা যায়।
প্রথম উদাহরণ: Native Query দিয়ে Employee List Extraction
ধরা যাক, আমাদের একটি Employee Entity আছে এবং আমরা Employee টেবিল থেকে সমস্ত কর্মচারীকে বের করতে চাই, কিন্তু এই কুয়েরি Native SQL তে হবে।
Step 1: Employee Entity
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
public class Employee {
@Id
private Long id;
private String name;
private double salary;
private String department;
// Getter and Setter Methods
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
}
Step 2: Native SQL Query for Employee List
এখন, আমরা Native SQL Query ব্যবহার করে Employee টেবিল থেকে সমস্ত কর্মচারীর নাম এবং বেতন বের করতে চাই।
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Employee> getAllEmployees() {
// Native SQL Query to fetch all employees
String sql = "SELECT * FROM Employee";
Query query = entityManager.createNativeQuery(sql, Employee.class);
// Fetching results as List of Employee objects
return query.getResultList(); // Execute the query and return the result
}
}
ব্যাখ্যা:
- createNativeQuery: এটি Native SQL Query তৈরি করতে ব্যবহৃত হয় এবং ডেটাবেসের আসল SQL ব্যবহার করতে সহায়তা করে।
- Employee.class: এটি Entity ক্লাস, যার মাধ্যমে
Employeeটেবিলের ডেটা Java Object হিসেবে ম্যাপ হয়। - getResultList(): এটি Native Query এর রেজাল্টের লিস্ট ফেরত দেয়।
দ্বিতীয় উদাহরণ: Native SQL Query দিয়ে Aggregate Data Extraction
ধরা যাক, আমরা Employee টেবিল থেকে department অনুযায়ী গড় বেতন বের করতে চাই, এবং HAVING ক্লজ ব্যবহার করে শুধুমাত্র সেই বিভাগের কর্মচারী গুলি দেখতে চাই যাদের গড় বেতন ৫০,০০০ টাকার বেশি।
Step 1: Aggregate Query with Group By and Having
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
import java.util.Object;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Object[]> getAverageSalaryByDepartment() {
// Native SQL Query with GROUP BY and HAVING
String sql = "SELECT department, AVG(salary) FROM Employee " +
"GROUP BY department HAVING AVG(salary) > 50000";
Query query = entityManager.createNativeQuery(sql);
// Fetching aggregated data
return query.getResultList(); // Execute the query and return the result
}
}
ব্যাখ্যা:
- AVG(salary): গড় বেতন বের করার জন্য AVG aggregate function ব্যবহার করা হয়েছে।
- GROUP BY: ডেটা department অনুযায়ী গ্রুপ করা হয়েছে।
- HAVING: গড় বেতন ৫০,০০০ টাকার বেশি এমন বিভাগগুলিই ফিল্টার করা হয়েছে।
এই কুয়েরি ব্যবহারের মাধ্যমে, আপনি department এবং গড় বেতন জানিয়ে বিভিন্ন বিভাগে কর্মচারীদের গড় বেতন বের করতে পারবেন।
তৃতীয় উদাহরণ: Native SQL Query দিয়ে Employee Pagination
আমরা যদি Employee টেবিলের ডেটা পেজিনেশন করতে চাই, তবে Native SQL Query এর মাধ্যমে তা করা সম্ভব। এখানে আমরা প্রথম ৫টি কর্মচারী দেখতে চাই, যারা HR বিভাগে কর্মরত।
Step 1: Native Query with Pagination
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Employee> getEmployeesByDepartmentWithPagination(String department) {
// Native SQL Query with Pagination
String sql = "SELECT * FROM Employee WHERE department = :department";
Query query = entityManager.createNativeQuery(sql, Employee.class);
query.setParameter("department", department);
query.setFirstResult(0); // Start from the first result
query.setMaxResults(5); // Limit the results to 5
return query.getResultList(); // Fetch the paginated results
}
}
ব্যাখ্যা:
- setFirstResult(0): এটি প্রথম ৫টি রেকর্ড থেকে শুরু করবে (যেহেতু আমরা ৫টি রেকর্ডের জন্য সিলেক্ট করেছি)।
- setMaxResults(5): এটি ৫টি রেকর্ডে সীমাবদ্ধ করবে, অর্থাৎ, পেজিনেশন এর মাধ্যমে ৫টি কর্মচারী রিটার্ন করবে।
এখানে, HR ডিপার্টমেন্টের প্রথম ৫টি কর্মচারী ফেরত আসবে।
চতুর্থ উদাহরণ: Native SQL Query with JOINs
আমরা যদি Employee এবং Department টেবিলের মধ্যে JOIN করতে চাই, তবে Native SQL Query এর মাধ্যমে তা করা যাবে।
Step 1: Native SQL Query with JOIN
import javax.persistence.EntityManager;
import javax.persistence.Query;
import java.util.List;
public class EmployeeService {
private EntityManager entityManager;
public EmployeeService(EntityManager entityManager) {
this.entityManager = entityManager;
}
public List<Object[]> getEmployeeDepartmentDetails() {
// Native SQL Query with JOIN operation
String sql = "SELECT e.name, e.salary, d.name FROM Employee e " +
"INNER JOIN Department d ON e.department_id = d.id";
Query query = entityManager.createNativeQuery(sql);
// Fetching employee name, salary, and department name
return query.getResultList(); // Execute the query and return the result
}
}
ব্যাখ্যা:
- INNER JOIN:
EmployeeএবংDepartmentটেবিলের মধ্যে INNER JOIN ব্যবহার করা হয়েছে। - Object[]: রিটার্ন টাইপ
Object[]কারণ একাধিক কলাম (যেমন,Employeeএর নাম, বেতন এবংDepartmentএর নাম) একত্রে রিটার্ন করা হচ্ছে।
এটি Employee টেবিল এবং Department টেবিলের সংযুক্ত ডেটা (employee name, salary, department name) রিটার্ন করবে।
সারাংশ
Native SQL Queries JPA তে ডেটাবেস নির্দিষ্ট কুয়েরি এবং জটিল অপারেশন করার জন্য শক্তিশালী উপায়। আপনি joins, aggregation functions, subqueries, এবং pagination এর মতো কমপ্লেক্স ডেটাবেস অপারেশন Native SQL Query ব্যবহার করে সহজেই করতে পারেন। এগুলির মাধ্যমে আপনি ডেটাবেসের বিশেষ ক্ষমতাগুলো ব্যবহার করে ডেটা এক্সট্র্যাকশন করতে পারেন। EntityManager এর মাধ্যমে createNativeQuery() মেথড ব্যবহার করে Native Queries চালানো হয় এবং আপনি সহজেই Entity, Object[] অথবা DTO তে রেজাল্ট ম্যাপ করতে পারেন।
Read more